package sjg.DataStructures.stack;

/**
 * 加减乘除 计算器
 */
public class Calculator {
    public static void main(String[] args) {
        // 假设只有10以内的数字并且符号只有加减乘除
        String expression = "777*2/7+9*2";
        int calculate = calculate(expression);
        System.out.println("计算结果：" + calculate);
    }

    // 计算器
    public static int calculate(String expression) {
        // 数栈
        ArrayStack2 numStack = new ArrayStack2(10);
        // 符号栈
        ArrayStack2 signStack = new ArrayStack2(10);
        char[] chars = expression.toCharArray();
        if (signStack.isOper(chars[0])) {
            System.out.println("该计算式不符合规则~");
            return -1;
        }
        boolean canCal = false;
        boolean isKeepNum = false;
        for (char aChar : chars) {
            // 将操作数压栈
            if (signStack.isOper(aChar)) {
                signStack.push(aChar);
                // 判断优先级
                if (signStack.priority(aChar) == 2) {
                    canCal = true;
                }
                isKeepNum = false;
            } else {
                numStack.push(Integer.parseInt(String.valueOf(aChar)));
                // 判断是否可以拼接
                if (isKeepNum) {
                    int num2 = numStack.pop();
                    int num1 = numStack.pop();
                    String val = String.valueOf(num1) + String.valueOf(num2);
                    // 拼接
                    numStack.push(Integer.parseInt(val));
                }
                // 判断是否可以计算
                if (canCal) {
                    int num2 = numStack.pop();
                    int num1 = numStack.pop();
                    int sign = signStack.pop();
                    int val = calculate(num1, num2, sign);
                    numStack.push(val);
                    canCal = false;
                }
                isKeepNum = true;
            }
        }
        // 开始计算+-
        while (!signStack.isEmpty()) {
            int num2 = numStack.pop();
            int num1 = numStack.pop();
            int sign = signStack.pop();
            int val = calculate(num1, num2, sign);
            numStack.push(val);
        }
        return numStack.peek();
    }

    // 计算方法
    public static int calculate(int n, int m, int oper) {
        switch (oper) {
            case '*':
                return n * m;
            case '/':
                return n / m;
            case '+':
                return n + m;
            case '-':
                return n - m;
            default:
                break;
        }
        return 0;
    }


}


// ArrayStack2 表示栈
class ArrayStack2 {
    private int maxSize; // 表示栈大小
    private int[] stack; // 数组，模拟栈
    private int top = -1; //top表示栈顶，初始化为 -1

    // 构造器
    public ArrayStack2(int maxSize) {
        this.maxSize = maxSize;
        stack = new int[maxSize];
    }

    // 判断占满
    public boolean isFull() {
        return top == maxSize - 1;
    }

    // 判断栈空
    public boolean isEmpty() {
        return top == -1;
    }

    // 入栈
    public void push(int val) {
        // 判断栈满
        if (isFull()) {
            System.out.println("栈满~~");
            return;
        }
        top++;
        stack[top] = val;
    }

    // 出栈
    public int pop() {
        // 判断栈空
        if (isEmpty()) {
            System.out.println("栈空~~");
            throw new RuntimeException("栈空~");
        }
        top--;
        return stack[top + 1];
    }

    //遍历栈
    public void list() {
        // 遍历数组
        for (int i = 0; i <= top; i++) {
            System.out.println(stack[i]);
        }
    }

    // 返回运算符的优先级，使用数字表示
    // 数字越大，优先级越高
    public int priority(int oper) {
        if (oper == '*' || oper == '/') {
            return 2;
        } else if (oper == '+' || oper == '-') {
            return 1;
        } else {
            return -1; // 认为是有问题的，不支持
        }
    }

    // 判定是否是一个运算符
    public boolean isOper(char val) {
        return val == '*' || val == '/' || val == '+' || val == '-';
    }

    public int peek() {
        if (isEmpty()) {
            System.out.println("栈空~");
            throw new RuntimeException("栈空~");
        }
        return stack[top];
    }
}